const dbUtil = require('../util/dbutil');


class SqlWhere {
    /**
     *构造函数，用于创建 SqlWhere 对象
     *@param {string} head - 查询头部
     *@param {object} body - 请求数据体
     */
    constructor(head, body) {
        //查询头
        this.head = head;
        //查询条件
        this.where = [];
        //查询参数
        this.queryParameters = [];
        //查询模式-默认查全部
        this.queryMode = dbUtil.getAll;
        //自定义命令
        this.customCommands = [];
        //分页sql
        this.pagination = null;
        //请求数据
        this.body = body
        //查询条件前缀
        this.queryConditionPrefix = '';
        return this;
    }


    //设置查询条件前缀
    setQueryConditionPrefix(sql) {
        this.queryConditionPrefix = sql;
        return this;
    }

    /**
     *设置分页是否开启
     *@param {boolean} isOpen - 是否开启分页
     *@return {SqlWhere} 返回当前对象
     **/
    setPagination(isOpen= true) {
        if (isOpen) {
            //如果前端传来数据pageSize和pageNum都在，就添加查询语句
            if (this.body.pageSize && this.body.pageNum) {
                this.pagination = `LIMIT ${this.body.pageSize} OFFSET ${(this.body.pageNum - 1) * this.body.pageSize}`;
            } else {
                this.pagination = null;
            }
        } else {
            this.pagination = null;
        }
        return this;
    }

    /**
     *添加查询尾自定义命令
     *@param {string} val - 自定义命令
     *@return {SqlWhere} 返回当前对象
     **/
    setCustomCommands(val) {
        this.customCommands.push(val);
        return this;
    }

    /**
     *设置查询模式
     *@param {function} func - sql最终执行函数
     *@return {SqlWhere} 返回当前对象
     **/
    setQueryMode(func) {
        this.queryMode = func;
        return this;
    }

    /**
     *设置查询头
     *@param {string} val - 查询头
     *@return {SqlWhere} 返回当前对象
     **/
    setQueryHeader(val) {
        this.head = val;
        return this;
    }

    /**
     *添加查询条件-单个
     *@param {string} sql - 查询语句
     *@param {*} val - 参数
     *@return {SqlWhere} 返回当前对象
     **/
    addQueryCriteria(sql, val) {
        this.where.push(sql);
        //数据就添加
        val && this.queryParameters.push(val);
        return this;
    }

    /**
     *添加查询条件-多个
     *@param {array} arr - 查询条件数组- ['id','name'...]
     *@return {SqlWhere} 返回当前对象
     **/
    addQueryCriteriaMultiple(arr) {
        arr.forEach(item => {
            //去除%符号
            const key = item.includes("%") ? item.split("%").join('') : item;
            //判断条件是否满足,满足就添加查询条件
            if (this.body[key] && this.body[key] && this.body[key] !== 0 && this.body[key] !== 0) {
                //查询语句
                let queryStatements = '';
                //判断是否模糊查询
                if (item.includes("%")) {
                    queryStatements = `${key} like ?`;
                    this.queryParameters.push(`%${this.body[key]}%`);
                } else {
                    queryStatements = `${key} = ?`;
                    this.queryParameters.push(this.body[key]);
                }
                //添加查询语句
                this.where.push(this.queryConditionPrefix + queryStatements);
            }
        });
        return this;
    }

    /**
     * 获取查询条件
     *@return {string} 获取查询字符串
     **/
    getQueryCriteria() {
        let whereText = '';
        //添加查询命令
        this.where.forEach(item => whereText += `${item} AND `);
        //去除最后的AND
        return this.where.length === 0 ? "" : ` WHERE ${whereText.substring(0, whereText.length - 4)}`;
    }

    /**
     *获取执行命令
     *@return {string} 执行命令字符串
     **/
    getTheExecutionCommand() {
        if (this.head.length !== ' ') {
            this.head += ' ';
        }
        let whereText = this.getQueryCriteria();
        //添加自定义命令
        this.customCommands.forEach(item => whereText += item);
        //添加查询头
        whereText = this.head + whereText;
        //分页语被设置，则添加分页数据
        if (this.pagination !== null) {
            whereText += this.pagination;
        }
        return whereText;
    }

    /**
     *获取执行参数
     *@return {array} 执行参数数组
     **/
    getExecutionParameters() {
        return this.queryParameters;
    }

    /**
     *执行查询
     *@return {Promise} 返回查询到的数据
     **/
    async executeTheQuery() {
        // 执行查询
        return await this.queryMode(this.getTheExecutionCommand(), this.getExecutionParameters());
    }
}


module.exports = SqlWhere;